package com.tokenmaster.aitrade.trade.boll;

import java.util.List;

import org.apache.log4j.Logger;

import com.tokenmaster.aitrade.common.system.KLinePoint;
import com.tokenmaster.aitrade.data.SystemDB;

/**
 * @author buxinyun
 * @Description: BOLL线指标
 * @date 2018年6月2日
 */
public class Index_boll {

	private static Logger logger = Logger.getLogger(Index_boll.class);

	private SystemDB systemDB = SystemDB.getInstance();

	public Index_Boll_Info calculation(KLinePoint kLinePoint) {

		// 获取 K 线

		List<KLinePoint> kLinePoints = systemDB.getKLinePointsBefore(kLinePoint.getSymbol(), kLinePoint.getType(),
				kLinePoint.getUnixTime(), 20);

		Index_Boll_Info index_Boll_Info = calculation(kLinePoints);

		return index_Boll_Info;
	}

	/**
	 * @param klines
	 */
	public Index_Boll_Info calculation(List<KLinePoint> klines) {

		Index_Boll_Info index_Boll_Info = new Index_Boll_Info();

		KLinePoint lastKline = klines.get(klines.size() - 1);

		// indexBollInfo 属性赋值
		index_Boll_Info.setSymbol(lastKline.getSymbol());
		index_Boll_Info.setType(lastKline.getType());
		// 计算MA
		double[] ma = new double[klines.size()];
		calculationMA(klines, ma);
		// 计算 up,down 布林线
		double[] boll_up = new double[klines.size()];
		double[] boll_down = new double[klines.size()];
		calculationMD(klines, ma, boll_up, boll_down);

		index_Boll_Info.setUnixTime(klines.get(klines.size() - 1).getUnixTime());
		// 上轨
		index_Boll_Info.setUpPrice(boll_up[klines.size() - 1]);
		// 下轨
		index_Boll_Info.setDownPrice(boll_down[klines.size() - 1]);
		// 中轨
		index_Boll_Info.setMidPrice(ma[klines.size() - 1]);

		// 当前价格
		index_Boll_Info.setCurrentPrice(klines.get(klines.size() - 1).getLast());

		// 2倍上轨
		index_Boll_Info.setDouble_upPrice(
				(index_Boll_Info.getUpPrice() - index_Boll_Info.getMidPrice()) * 2 + index_Boll_Info.getMidPrice());
		// 2倍下轨
		index_Boll_Info.setDouble_downPrice(
				index_Boll_Info.getMidPrice() - (index_Boll_Info.getMidPrice() - index_Boll_Info.getDownPrice()) * 2);

		if (index_Boll_Info.getCurrentPrice() >= index_Boll_Info.getDouble_upPrice()) {
			// 2倍上轨
			index_Boll_Info.setPosition(6);

		} else if (index_Boll_Info.getCurrentPrice() >= index_Boll_Info.getUpPrice()) {
			// 2倍上轨与上轨之间
			index_Boll_Info.setPosition(5);

		} else if (index_Boll_Info.getCurrentPrice() >= index_Boll_Info.getMidPrice()) {
			// 上轨与中轨之间
			index_Boll_Info.setPosition(4);

		} else if (index_Boll_Info.getCurrentPrice() >= index_Boll_Info.getDownPrice()) {
			// 下轨与中轨之间
			index_Boll_Info.setPosition(3);

		} else if (index_Boll_Info.getCurrentPrice() >= index_Boll_Info.getDouble_downPrice()) {
			// 下轨与2倍下轨之间
			index_Boll_Info.setPosition(2);
		} else {
			index_Boll_Info.setPosition(1);
		}

		return index_Boll_Info;
	}

	/**
	 * 计算20日的移动平均线
	 *
	 * @return
	 */
	private void calculationMA(List<KLinePoint> Klines, double[] ma) {

		for (int i = 0; i < Klines.size(); i++) {

			double totalSum = 0;

			if (i < 20) {

				for (int j = 0; j <= i; j++) {
					KLinePoint kLinePoint = Klines.get(j);
					totalSum = totalSum + kLinePoint.getLast();

				}
				double average = totalSum / (i + 1);
				ma[i] = average;

			} else {
				for (int j = i - 19; j <= i; j++) {
					KLinePoint kLinePoint = Klines.get(j);
					totalSum = totalSum + kLinePoint.getLast();
				}
				double average = totalSum / 20;
				ma[i] = average;
			}
		}
	}

	/**
	 * 计算 MD
	 *
	 * @param Klines
	 * @param ma
	 * @param boll_up
	 * @param boll_down
	 */
	private void calculationMD(List<KLinePoint> Klines, double[] ma, double[] boll_up, double[] boll_down) {

		for (int i = 0; i < Klines.size(); i++) {

			double totalSum = 0;

			if (i < 20) {

				for (int j = 0; j <= i; j++) {
					KLinePoint kLinePoint = Klines.get(j);
					totalSum = totalSum + (kLinePoint.getLast() - ma[i]) * (kLinePoint.getLast() - ma[i]);

				}
				double average = totalSum / (i + 1);
				double md = Math.sqrt(average);

				boll_up[i] = md * 2 + ma[i];
				boll_down[i] = ma[i] - md * 2;

			} else {
				for (int j = i - 19; j <= i; j++) {
					KLinePoint kLinePoint = Klines.get(j);
					totalSum = totalSum + (kLinePoint.getLast() - ma[i]) * (kLinePoint.getLast() - ma[i]);
				}
				double average = totalSum / 20;
				double md = Math.sqrt(average);

				boll_up[i] = md * 2 + ma[i];
				boll_down[i] = ma[i] - md * 2;
			}
		}

	}

}
